package app.r_teenus.backend.dao;


import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.FilterDefs;
import org.hibernate.annotations.ParamDef;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import app.r_teenus.backend.model.Address;
import app.r_teenus.backend.model.Contact;
import app.r_teenus.backend.model.Employee;
import app.r_teenus.backend.model.Enterprise;
import app.r_teenus.backend.model.UserAccount;


@Repository("enterpriseDao")
@FilterDefs({ @FilterDef(name = "SUBJECT_TYPE", parameters = @ParamDef(name = "SUBJECT_TYPE", type = "integer")), 
@FilterDef(name = "CONTACT_TYPE", parameters = @ParamDef(name = "CONTACT_TYPE", type = "integer")), 
@FilterDef(name = "SUBJECTATTRIBUTE_TYPE", parameters = @ParamDef(name = "SUBJECTATTRIBUTE_TYPE", type = "integer")) })
public class EnterpriseDaoImpl extends DefaultDaoImpl implements EnterpriseDao {

	public List<Enterprise> findEnterprises() {
		List<Enterprise> enterprises_list = hibernateTemplate.loadAll(Enterprise.class);
		return enterprises_list;
	}

	/**
	 * Find enterprises.
	 */
	@Transactional(readOnly = false)
	public Enterprise findEnterpriseById(Integer id) {
		hibernateTemplate.getSessionFactory().getCurrentSession().enableFilter("SUBJECT_TYPE").setParameter("SUBJECT_TYPE", 2);
		hibernateTemplate.getSessionFactory().getCurrentSession().enableFilter("SUBJECTATTRIBUTE_TYPE").setParameter("SUBJECTATTRIBUTE_TYPE", 2);
		hibernateTemplate.getSessionFactory().getCurrentSession().enableFilter("CONTACT_TYPE").setParameter("CONTACT_TYPE", 2);
		Enterprise enterprise = hibernateTemplate.get(Enterprise.class, id);
		hibernateTemplate.initialize(enterprise.getAddresses());
		hibernateTemplate.initialize(enterprise.getContacts());
		hibernateTemplate.initialize(enterprise.getEmployee());
		return enterprise;
	}

	@Transactional(readOnly = false)
	public Enterprise save(Enterprise enterprise) {

		Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		Employee employee = null;
		if (principal instanceof UserDetails) {

			String userName = ((UserDetails) principal).getUsername();
			String userPassword = ((UserDetails) principal).getPassword();
			Employee employeeTmp = new Employee();
			UserAccount userAccount = new UserAccount(userName, userPassword);
			employeeTmp.setUserAccount(new ArrayList<UserAccount>());
			employeeTmp.getUserAccount().add(userAccount);
			employee = (Employee) hibernateTemplate.findByExample(employeeTmp).get(0);
		}

		if (enterprise.getId() != null) {
			enterprise.setUpdated(new Timestamp(new Date().getTime()));
			enterprise.setUpdatedBy(employee);

		} else {
			enterprise.setCreated(new Timestamp(new Date().getTime()));
			enterprise.setCreatedBy(employee);
		}

		hibernateTemplate.saveOrUpdate(enterprise);
		return enterprise;
	}

	/**
	 * Saves address to Enterprise. //
	 */
	@Transactional(readOnly = false)
	public Enterprise saveAddress(Enterprise enterprise, Address address) {
		address.setAddressType(findAddressTypeById(address.getAddressTypeId()));
		if (address.getId() != null) {
			for (Address addre : enterprise.getAddresses()) {
				if (addre.getId().intValue() == address.getId().intValue()) {
					enterprise.getAddresses().remove(addre);
					break;
				}
			}
		} else {
			address.setSubject(enterprise.getId());
			address.setSubjectType(2);
		}
		enterprise.getAddresses().add(address);
		hibernateTemplate.saveOrUpdate(address);
		return enterprise;
	}

	/**
	 * Saves address to Enterprise. //
	 */
	@Transactional(readOnly = false)
	public Enterprise saveContact(Enterprise enterprise, Contact contact) {
		contact.setContactType(findContactTypeById(contact.getContactTypeId()));
		if (contact.getId() != null) {
			for (Contact cont : enterprise.getContacts()) {
				if (cont.getId().intValue() == contact.getId().intValue()) {
					enterprise.getContacts().remove(cont);
					break;
				}
			}
		} else {
			contact.setSubject(enterprise.getId());
			contact.setSubjectType(2);
		}
		enterprise.getContacts().add(contact);

		hibernateTemplate.saveOrUpdate(contact);
		return enterprise;
	}

	@Transactional(readOnly = false)
	public void delete(Enterprise enterprise) {
		hibernateTemplate.getSessionFactory().getCurrentSession().enableFilter("SUBJECT_TYPE").setParameter("SUBJECT_TYPE", 2);
		hibernateTemplate.getSessionFactory().getCurrentSession().enableFilter("SUBJECTATTRIBUTE_TYPE").setParameter("SUBJECTATTRIBUTE_TYPE", 2);
		hibernateTemplate.getSessionFactory().getCurrentSession().enableFilter("CONTACT_TYPE").setParameter("CONTACT_TYPE", 2);
		enterprise = hibernateTemplate.get(Enterprise.class, enterprise.getId());
		hibernateTemplate.initialize(enterprise.getAddresses());
		hibernateTemplate.initialize(enterprise.getContacts());
		hibernateTemplate.initialize(enterprise.getEmployee());
//		enterprise.getSubjectAttributes().size();
//		enterprise.getAddresses().size();
//		enterprise.getContacts().size();
		hibernateTemplate.delete(enterprise);
	}

	/**
	 * Deletes contact from Enterprise.
	 */
	@Transactional(readOnly = false)
	public Enterprise deleteContact(Enterprise Enterprise, Integer contactId) {
		for (Contact cont : Enterprise.getContacts()) {
			if (cont.getId().intValue() == contactId.intValue()) {
				hibernateTemplate.delete(cont);
				Enterprise.getContacts().remove(cont);
				break;
			}
		}
		return Enterprise;
	}

	/**
	 * Deletes address from Enterprise.
	 */
	@Transactional(readOnly = false)
	public Enterprise deleteAddress(Enterprise Enterprise, Integer addressId) {
		for (Address a : Enterprise.getAddresses()) {
			if (a.getId().intValue() == addressId.intValue()) {
				hibernateTemplate.delete(a);
				Enterprise.getAddresses().remove(a);
				break;
			}
		}
		return Enterprise;
	}
}
